home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / ddj0897.zip / RCSC.ZIP / SRC / CC4.C < prev    next >
C/C++ Source or Header  |  1997-01-12  |  25KB  |  806 lines

  1. /*
  2. ** Concurrent Small C Language Features Added by Andy Yuen 1997
  3. ** Plus minor optimization bug fixes.
  4. ** Small-C Compiler -- Part 4 -- Back End.
  5. ** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix
  6. ** All rights reserved.
  7. */
  8. #include <stdio.h>
  9. #include "cc.h"
  10.  
  11. /* #define DISOPT */       /* display optimizations values */
  12. char tmpbuf[256];
  13. /*************************** externals ****************************/
  14.  
  15. extern char
  16.   *cptr, *macn, *litq, *symtab, optimize, ssname[NAMESIZE];
  17.  
  18. extern int
  19.   *stage, litlab, litptr, csp, output, oldseg, usexpr,
  20.   *snext, *stail, *slast;
  21.  
  22.  
  23. /***************** optimizer command definitions ******************/
  24.  
  25.              /*     --      p-codes must not overlap these */
  26. #define any     0x00FF   /* matches any p-code */
  27. #define _pop    0x00FE   /* matches if corresponding POP2 exists */
  28. #define pfree   0x00FD   /* matches if pri register free */
  29. #define sfree   0x00FC   /* matches if sec register free */
  30. #define comm    0x00FB   /* matches if registers are commutative */
  31.  
  32.              /*     --      these digits are reserved for n */
  33. #define go      0x0100   /* go n entries */
  34. #define gc      0x0200   /* get code from n entries away */
  35. #define gv      0x0300   /* get value from n entries away */
  36. #define sum     0x0400   /* add value from nth entry away */
  37. #define neg     0x0500   /* negate the value */
  38. #define ife     0x0600   /* if value == n do commands to next 0 */
  39. #define ifl     0x0700   /* if value <  n do commands to next 0 */
  40. #define swv     0x0800   /* swap value with value n entries away */
  41. #define topop   0x0900   /* moves |code and current value to POP2 */
  42.  
  43. #define p1      0x0001   /* plus 1 */
  44. #define p2      0x0002   /* plus 2 */
  45. #define p3      0x0003   /* plus 3 */
  46. #define p4      0x0004   /* plus 4 */
  47. #define m1      0x00FF   /* minus 1 */
  48. #define m2      0x00FE   /* minus 2 */
  49. #define m3      0x00FD   /* minus 3 */
  50. #define m4      0x00FC   /* minus 4 */
  51.  
  52. #define PRI      0030    /* primary register bits */
  53. #define SEC      0003    /* secondary register bits */
  54. #define USES     0011    /* use register contents */
  55. #define ZAPS     0022    /* zap register contents */
  56. #define PUSHES   0100    /* pushes onto the stack */
  57. #define COMMUTES 0200    /* commutative p-code */
  58.  
  59. #define TERMMARK "DW 1A1AH"    /* special marker to terminate table */
  60.  
  61. /******************** optimizer command lists *********************/
  62.  
  63. int
  64.   seq00[] = {0,ADD12,MOVE21,0,                       /* ADD21 */
  65.              go|p1,ADD21,0},
  66.  
  67.   seq01[] = {0,ADD1n,0,                              /* rINC1 or rDEC1 ? */ 
  68.              ifl|m2,0,ifl|0,rDEC1,neg,0,ifl|p3,rINC1,0,0},
  69.  
  70.   seq02[] = {0,ADD2n,0,                              /* rINC2 or rDEC2 ? */ 
  71.              ifl|m2,0,ifl|0,rDEC2,neg,0,ifl|p3,rINC2,0,0},
  72.  
  73.   seq03[] = {0,rDEC1,PUTbp1,rINC1,0,                 /* SUBbpn or DECbp */
  74.              go|p2,ife|p1,DECbp,0,SUBbpn,0},
  75.  
  76.   seq04[] = {0,rDEC1,PUTwp1,rINC1,0,                 /* SUBwpn or DECwp */
  77.              go|p2,ife|p1,DECwp,0,SUBwpn,0},
  78.  
  79.   seq05[] = {0,rDEC1,PUTbm1,rINC1,0,                 /* SUB_m_ COMMAn */
  80.              go|p1,SUB_m_,go|p1,COMMAn,go|m1,0},
  81.  
  82.   seq06[] = {0,rDEC1,PUTwm1,rINC1,0,                 /* SUB_m_ COMMAn */
  83.              go|p1,SUB_m_,go|p1,COMMAn,go|m1,0},
  84.  
  85.   /* added sfree to fix bug: seq48 added for special case */
  86.   seq07[] = {0,GETw1m,GETw2n,ADD12,MOVE21,GETb1p,sfree,0,  /* GETw2m GETb1p */
  87.              go|p4,gv|m3,go|m1,GETw2m,gv|m3,0},
  88.  
  89.   /* added sfree to fix bug: seq49 added for special case */
  90.   seq08[] = {0,GETw1m,GETw2n,ADD12,MOVE21,GETb1pu,sfree,0, /* GETw2m GETb1pu */
  91.              go|p4,gv|m3,go|m1,GETw2m,gv|m3,0},
  92.  
  93.   /* added sfree to fix bug: seq50 added for special case */
  94.   seq09[] = {0,GETw1m,GETw2n,ADD12,MOVE21,GETw1p,sfree,0,  /* GETw2m GETw1p */
  95.              go|p4,gv|m3,go|m1,GETw2m,gv|m3,0},
  96.  
  97.   seq10[] = {0,GETw1m,GETw2m,SWAP12,0,               /* GETw2m GETw1m */
  98.              go|p2,GETw1m,gv|m1,go|m1,gv|m1,0},
  99.  
  100.   seq11[] = {0,GETw1m,MOVE21,0,                      /* GETw2m */
  101.              go|p1,GETw2m,gv|m1,0},
  102.  
  103.   seq12[] = {0,GETw1m,PUSH1,pfree,0,                 /* PUSHm */
  104.              go|p1,PUSHm,gv|m1,0},
  105.  
  106.   seq13[] = {0,GETw1n,PUTbm1,pfree,0,                /* PUT_m_ COMMAn */
  107.              PUT_m_,go|p1,COMMAn,go|m1,swv|p1,0},
  108.  
  109.   seq14[] = {0,GETw1n,PUTwm1,pfree,0,                /* PUT_m_ COMMAn */ 
  110.              PUT_m_,go|p1,COMMAn,go|m1,swv|p1,0}, 
  111.  
  112.   seq15[] = {0,GETw1p,PUSH1,pfree,0,                 /* PUSHp */ 
  113.              go|p1,PUSHp,gv|m1,0},
  114.  
  115.   seq16[] = {0,GETw1s,GETw2n,ADD12,MOVE21,0,         /* GETw2s ADD2n */
  116.              go|p3,ADD2n,gv|m2,go|m1,GETw2s,gv|m2,0},
  117.  
  118.   seq17[] = {0,GETw1s,GETw2s,SWAP12,0,               /* GETw2s GETw1s */
  119.              go|p2,GETw1s,gv|m1,go|m1,GETw2s,gv|m1,0},
  120.  
  121.   seq18[] = {0,GETw1s,MOVE21,0,                      /* GETw2s */
  122.              go|p1,GETw2s,gv|m1,0},
  123.  
  124.   seq19[] = {0,GETw2m,GETw1n,SWAP12,SUB12,0,         /* GETw1m SUB1n */
  125.              go|p3,SUB1n,gv|m2,go|m1,GETw1m,gv|m2,0},
  126.  
  127.   seq20[] = {0,GETw2n,ADD12,0,                       /* ADD1n */ 
  128.              go|p1,ADD1n,gv|m1,0},
  129.  
  130.   seq21[] = {0,GETw2s,GETw1n,SWAP12,SUB12,0,         /* GETw1s SUB1n */ 
  131.              go|p3,SUB1n,gv|m2,go|m1,GETw1s,gv|m2,0},
  132.  
  133.   seq22[] = {0,rINC1,PUTbm1,rDEC1,0,                 /* ADDm_ COMMAn */ 
  134.              go|p1,ADDm_,go|p1,COMMAn,go|m1,0}, 
  135.  
  136.   seq23[] = {0,rINC1,PUTwm1,rDEC1,0,                 /* ADDm_ COMMAn */ 
  137.              go|p1,ADDm_,go|p1,COMMAn,go|m1,0}, 
  138.  
  139.   seq24[] = {0,rINC1,PUTbp1,rDEC1,0,                 /* ADDbpn or INCbp */ 
  140.              go|p2,ife|p1,INCbp,0,ADDbpn,0}, 
  141.  
  142.   seq25[] = {0,rINC1,PUTwp1,rDEC1,0,                 /* ADDwpn or INCwp */ 
  143.              go|p2,ife|p1,INCwp,0,ADDwpn,0}, 
  144.  
  145.   seq26[] = {0,MOVE21,GETw1n,SWAP12,SUB12,0,         /* SUB1n */
  146.              go|p3,SUB1n,gv|m2,0},
  147.  
  148.   seq27[] = {0,MOVE21,GETw1n,comm,0,                 /* GETw2n comm */
  149.              go|p1,GETw2n,0},
  150.  
  151.   seq28[] = {0,POINT1m,GETw2n,ADD12,MOVE21,0,        /* POINT2m_ PLUSn */
  152.              go|p3,PLUSn,gv|m2,go|m1,POINT2m_,gv|m2,0},
  153.  
  154.   seq29[] = {0,POINT1m,MOVE21,pfree,0,               /* POINT2m */
  155.              go|p1,POINT2m,gv|m1,0},
  156.  
  157.   seq30[] = {0,POINT1m,PUSH1,pfree,_pop,0,           /* ... POINT2m */
  158.              topop|POINT2m,go|p2,0},
  159.  
  160.   seq31[] = {0,POINT1s,GETw2n,ADD12,MOVE21,0,        /* POINT2s */
  161.              sum|p1,go|p3,POINT2s,gv|m3,0},
  162.  
  163.   seq32[] = {0,POINT1s,PUSH1,MOVE21,0,               /* POINT2s PUSH2 */
  164.              go|p1,POINT2s,gv|m1,go|p1,PUSH2,go|m1,0},
  165.  
  166.   seq33[] = {0,POINT1s,PUSH1,pfree,_pop,0,           /* ... POINT2s */
  167.              topop|POINT2s,go|p2,0},
  168.  
  169.   seq34[] = {0,POINT1s,MOVE21,0,                     /* POINT2s */
  170.              go|p1,POINT2s,gv|m1,0},
  171.  
  172.   seq35[] = {0,POINT2m,GETb1p,sfree,0,               /* GETb1m */
  173.              go|p1,GETb1m,gv|m1,0},
  174.  
  175.   seq36[] = {0,POINT2m,GETb1pu,sfree,0,              /* GETb1mu */
  176.              go|p1,GETb1mu,gv|m1,0},
  177.  
  178.   seq37[] = {0,POINT2m,GETw1p,sfree,0,               /* GETw1m */
  179.              go|p1,GETw1m,gv|m1,0},
  180.  
  181.   seq38[] = {0,POINT2m_,PLUSn,GETw1p,sfree,0,        /* GETw1m_ PLUSn */
  182.              go|p2,gc|m1,gv|m1,go|m1,GETw1m_,gv|m1,0},
  183.  
  184.   seq39[] = {0,POINT2s,GETb1p,sfree,0,               /* GETb1s */
  185.              sum|p1,go|p1,GETb1s,gv|m1,0},
  186.  
  187.   seq40[] = {0,POINT2s,GETb1pu,sfree,0,              /* GETb1su */
  188.              sum|p1,go|p1,GETb1su,gv|m1,0},
  189.  
  190.   seq41[] = {0,POINT2s,GETw1p,PUSH1,pfree,0,         /* PUSHs */
  191.              sum|p1,go|p2,PUSHs,gv|m2,0},
  192.  
  193.   seq42[] = {0,POINT2s,GETw1p,sfree,0,               /* GETw1s */
  194.              sum|p1,go|p1,GETw1s,gv|m1,0},
  195.  
  196.   seq43[] = {0,PUSH1,any,POP2,0,                     /* MOVE21 any */
  197.              go|p2,gc|m1,gv|m1,go|m1,MOVE21,0},
  198.  
  199.   seq44[] = {0,PUSHm,_pop,0,                         /* ... GETw2m */
  200.              topop|GETw2m,go|p1,0},
  201.  
  202.   seq45[] = {0,PUSHp,any,POP2,0,                     /* GETw2p ... */
  203.              go|p2,gc|m1,gv|m1,go|m1,GETw2p,gv|m1,0},
  204.  
  205.   seq46[] = {0,PUSHs,_pop,0,                         /* ... GETw2s */
  206.              topop|GETw2s,go|p1,0},
  207.  
  208.   seq47[] = {0,SUB1n,0,                              /* rDEC1 or rINC1 ? */
  209.              ifl|m2,0,ifl|0,rINC1,neg,0,ifl|p3,rDEC1,0,0},
  210.  
  211.   /* start of extra optimizations for bug fixing: original optimizations
  212.      have side-effect that secondary register is not updated. If this
  213.      is followed by an instruction saving the updated result via
  214.      the secondary register, error occurs. The reason for
  215.      adding sfree in the original seq07, 08 and 09 is to avoid this.
  216.      The following 3 seqs optimize the problem cases. */
  217.  
  218.   seq48[] = {0,GETw1m,GETw2n,ADD12,MOVE21,GETb1p,0,  /* GETw2m GETb1p */
  219.              go|p3,gv|m2,ADD2n,go|m1,GETw2m,gv|m2,0},
  220.  
  221.   seq49[] = {0,GETw1m,GETw2n,ADD12,MOVE21,GETb1pu,0, /* GETw2m GETb1pu */
  222.              go|p3,gv|m2,ADD2n,go|m1,GETw2m,gv|m2,0},
  223.  
  224.   seq50[] = {0,GETw1m,GETw2n,ADD12,MOVE21,GETw1p,0,  /* GETw2m GETw1p */
  225.              go|p3,gv|m2,ADD2n,go|m1,GETw2m,gv|m2,0};
  226.  
  227. #define HIGH_SEQ  50
  228. int seq[HIGH_SEQ + 1];  
  229. setseq() {
  230.   seq[ 0] = seq00;  seq[ 1] = seq01;  seq[ 2] = seq02;  seq[ 3] = seq03;
  231.   seq[ 4] = seq04;  seq[ 5] = seq05;  seq[ 6] = seq06;  seq[ 7] = seq07;
  232.   seq[ 8] = seq08;  seq[ 9] = seq09;  seq[10] = seq10;  seq[11] = seq11;
  233.   seq[12] = seq12;  seq[13] = seq13;  seq[14] = seq14;  seq[15] = seq15;
  234.   seq[16] = seq16;  seq[17] = seq17;  seq[18] = seq18;  seq[19] = seq19;
  235.   seq[20] = seq20;  seq[21] = seq21;  seq[22] = seq22;  seq[23] = seq23;
  236.   seq[24] = seq24;  seq[25] = seq25;  seq[26] = seq26;  seq[27] = seq27;
  237.   seq[28] = seq28;  seq[29] = seq29;  seq[30] = seq30;  seq[31] = seq31;
  238.   seq[32] = seq32;  seq[33] = seq33;  seq[34] = seq34;  seq[35] = seq35;
  239.   seq[36] = seq36;  seq[37] = seq37;  seq[38] = seq38;  seq[39] = seq39;
  240.   seq[40] = seq40;  seq[41] = seq41;  seq[42] = seq42;  seq[43] = seq43;
  241.   seq[44] = seq44;  seq[45] = seq45;  seq[46] = seq46;  seq[47] = seq47;
  242.   seq[48] = seq48;  seq[49] = seq49;  seq[50] = seq50;  
  243.   } 
  244.  
  245. /***************** assembly-code strings ******************/
  246.  
  247. int code[PCODES];
  248.  
  249. /*
  250. ** First byte contains flag bits indicating:
  251. **    the value in ax is needed (010) or zapped (020)
  252. **    the value in bx is needed (001) or zapped (002)
  253. */
  254. setcodes() {
  255.   setseq();
  256.   code[ADD12]   = "\211ADD12\n";
  257.   code[ADD1n]   = "\010?ADD1n(<n>)\n??";
  258.   code[ADD21]   = "\211ADD21\n";
  259.   code[ADD2n]   = "\010?ADD2n(<n>)\n??";
  260.   code[ADDbpn]  = "\001ADDbpn(<n>)\n";
  261.   code[ADDwpn]  = "\001ADDwpn(<n>)\n";
  262.   code[ADDm_]   = "\000ADDm_(<m>)";
  263.   code[ADDSP]   = "\000?ADDSP(<n>)\n??";
  264.   code[AND12]   = "\211AND12\n";
  265.   code[ANEG1]   = "\010ANEG1\n";
  266.   code[ARGCNTn] = "\000ARGCNTn(<n>)\n";
  267.   code[ASL12]   = "\011ASL12\n";
  268.   code[ASR12]   = "\011ASR12\n";
  269.   code[CALL1]   = "\010CALL1\n";
  270.   code[CALLm]   = "\020CALLm(<m>)\n";
  271.   code[BYTE_]   = "\000 BYTE_ ";
  272.   code[BYTEn]   = "\000 BYTE_(<n>)\n";
  273.   code[BYTEr0]  = "\000 BYTEr0(<n>)\n";
  274.   code[COM1]    = "\010COM1\n";
  275.   code[COMMAn]  = "\000 COMMAn(<n>)\n";
  276.   code[DBL1]    = "\010DBL1\n";
  277.   code[DBL2]    = "\001DBL2\n";
  278.   code[DECbp]   = "\001DECbp\n";
  279.   code[DECwp]   = "\001DECwp\n";
  280.   code[DIV12]   = "\011DIV12\n";                 /* see gen() */
  281.   code[DIV12u]  = "\011DIV12u\n";            /* see gen() */
  282.   code[ENTER]   = "\100ENTER\n";
  283.   code[EQ10f]   = "\010EQ10f(_<n>)\n";
  284.   code[EQ12]    = "\211EQ12\n";
  285.   code[GE10f]   = "\010GE10f(_<n>)\n";
  286.   code[GE12]    = "\011GE12\n";
  287.   code[GE12u]   = "\011GE12u\n";
  288.   code[GETb1m]  = "\020GETb1m(<m>)\n";
  289.   code[GETb1mu] = "\020GETb1mu(<m>)\n";
  290.   code[GETb1p]  = "\021GETb1p(<n>)\n";       /* see gen() */
  291.   code[GETb1pu] = "\021GETb1pu(<n>)\n"; /* see gen() */
  292.   code[GETb1s]  = "\020GETb1s(<n>)\n";
  293.   code[GETb1su] = "\020GETb1su(<n>)\n";
  294.   code[GETw1m]  = "\020GETw1m(<m>)\n";
  295.   code[GETw1m_] = "\020GETw1m_(<m>)";
  296.   code[GETw1n]  = "\020GETw1n(<n>)\n";
  297.   code[GETw1p]  = "\021GETw1p(<n>)\n";            /* see gen() */
  298.   code[GETw1s]  = "\020GETw1s(<n>)\n";
  299.   code[GETw2m]  = "\002GETw2m(<m>)\n";
  300.   code[GETw2n]  = "\002GETw2n(<n>)\n";
  301.   code[GETw2p]  = "\021GETw2p(<n>)\n";
  302.   code[GETw2s]  = "\002GETw2s(<n>)\n";
  303.   code[GT10f]   = "\010GT10f(_<n>)\n";
  304.   code[GT12]    = "\010GT12\n";
  305.   code[GT12u]   = "\011GT12u\n";
  306.   code[INCbp]   = "\001INCbp\n";
  307.   code[INCwp]   = "\001INCwp\n";
  308.   code[WORD_]   = "\000WORD_ ";
  309.   code[WORDn]   = "\000WORDn(<n>)\n";
  310.   code[WORDr0]  = "\000WORDr0(<n>)\n";
  311.   code[JMPm]    = "\000JMPm(_<n>)\n";
  312.   code[LABm]    = "\000LABm(_<n>:)\n";
  313.   code[LE10f]   = "\010LE10f(_<n>)\n";
  314.   code[LE12]    = "\011LE12\n";
  315.   code[LE12u]   = "\011LE12u\n";
  316.   code[LNEG1]   = "\010LNEG1\n";
  317.   code[LT10f]   = "\010LT10f(_<n>)\n";
  318.   code[LT12]    = "\011LT12\n";
  319.   code[LT12u]   = "\011LT12u\n";
  320.   code[MOD12]   = "\011MOD12\n";      /* see gen() */
  321.   code[MOD12u]  = "\011MOD12u\n"; /* see gen() */
  322.   code[MOVE21]  = "\012MOVE21\n";
  323.   code[MUL12]   = "\211MUL12\n";
  324.   code[MUL12u]  = "\211MUL12u\n";
  325.   code[NE10f]   = "\010NE10f(_<n>)\n";
  326.   code[NE12]    = "\211NE12\n";
  327.   code[NEARm]   = "\000 NEARm(_<n>)\n";
  328.   code[OR12]    = "\211OR12\n";
  329.   code[PLUSn]   = "\000?PLUSn(<n>)??\n";
  330.   code[POINT1l] = "\020POINT1l(_<l>+<n>)\n";
  331.   code[POINT1m] = "\020POINT1m(<m>)\n";
  332.   code[POINT1s] = "\020POINT1s(<n>)\n";
  333.   code[POINT2m] = "\002POINT2m(<m>)\n";
  334.   code[POINT2m_]= "\002POINT2m_(<m>)";
  335.   code[POINT2s] = "\002POINT2s(<n>)\n";
  336.   code[POP2]    = "\002POP2\n";
  337.   code[PUSH1]   = "\110PUSH1\n";
  338.   code[PUSH2]   = "\101PUSH2\n";
  339.   code[PUSHm]   = "\100PUSHm(<m>)\n";
  340.   code[PUSHp]   = "\100PUSHp(<n>)\n";
  341.   code[PUSHs]   = "\100PUSHs(<n>)\n";
  342.   code[PUT_m_]  = "\000PUT_m_(<m>)";
  343.   code[PUTbm1]  = "\010PUTbm1(<m>)\n";
  344.   code[PUTbp1]  = "\011PUTbp1\n";
  345.   code[PUTwm1]  = "\010PUTwm1(<m>)\n";
  346.   code[PUTwp1]  = "\011PUTwp1\n";
  347.   code[rDEC1]   = "\010rDEC1(<n>)\n";
  348.   code[rDEC2]   = "\010rDEC2(<n>)\n";
  349.   code[REFm]    = "\000REFm(_<n>)";
  350.   code[RETURN]  = "\000RETURN(<n>)\n";
  351.   code[rINC1]   = "\010rINC1(<n>)\n";
  352.   code[rINC2]   = "\010rINC2(<n>)\n";
  353.   code[SUB_m_]  = "\000SUBm(<m>)";
  354.   code[SUB12]   = "\011SUB12\n";                    /* see gen() */
  355.   code[SUB1n]   = "\010?SUB1n(<n>)\n??";
  356.   code[SUBbpn]  = "\001SUBbpn(n>)\n";
  357.   code[SUBwpn]  = "\001SUBwpn(<n>)\n";
  358.   code[SWAP12]  = "\011SWAP12\n";
  359.   code[SWAP1s]  = "\012SWAP1s\n";
  360.   code[SWITCH]  = "\012SWITCH\n";
  361.   code[XOR12]   = "\211XOR12\n";
  362.   code[CSCINIT] = "\011CSCINIT\n";
  363.   code[ENTERM]    = "\000ENTERM\n";
  364.   code[EXITM]    = "\000EXITM\n";
  365.   }
  366.  
  367. /***************** code generation functions *****************/
  368.  
  369. /*
  370. ** print all assembler info before any code is generated
  371. ** and ensure that the segments appear in the correct order.
  372. */
  373. header()  {
  374.   toseg(CODESEG);
  375.   outline("CSCEXTRN");
  376. /*
  377.   outline("WORDn(0)"); 
  378. */
  379.   /* force non-zero code pointers, word alignment */
  380.   toseg(DATASEG);
  381. /*
  382.   outline("WORDn(0)");
  383. */
  384.  /* force non-zero data pointers, word alignment */
  385.   }
  386.  
  387. /*
  388. ** print any assembler stuff needed at the end
  389. */
  390. trailer()  {  
  391.   char *cp;
  392.   cptr = STARTGLB;
  393.   while(cptr < ENDGLB) {
  394.     if(cptr[IDENT] == FUNCTION && cptr[CLASS] == AUTOEXT)
  395.       external(cptr + NAME, 0, FUNCTION);
  396.     cptr += SYMMAX;
  397.     }
  398.   if((cp = findglb("main")) && cp[CLASS]==STATIC)
  399.     {
  400.     /* terminate the info segments */
  401.     outline("CSCTERM");
  402. /*
  403.     external("_main", 0, FUNCTION);
  404. */
  405.  
  406.     }
  407.   toseg(NULL);
  408.   outline("END");
  409. #ifdef DISOPT
  410.     {
  411.     int i, *count;
  412.     printf(";opt   count\n");
  413.     for(i = -1; ++i <= HIGH_SEQ; ) {
  414.       count = seq[i];
  415.       printf("; %2u   %5u\n", i, *count);
  416.       poll(YES);
  417.       }
  418.     }  
  419. #endif 
  420.   }
  421.  
  422. /*
  423. ** remember where we are in the queue in case we have to back up.
  424. */
  425. setstage(before, start) int *before, *start; {
  426.   if((*before = snext) == 0)
  427.     snext = stage;
  428.   *start = snext;
  429.   }
  430.  
  431. /*
  432. ** generate code in staging buffer.
  433. */
  434. gen(pcode, value) int pcode, value; {
  435.   int newcsp;
  436.   switch(pcode) {
  437.     case GETb1pu:
  438.     case GETb1p:
  439.     case GETw1p: gen(MOVE21, 0); break;
  440.     case SUB12:
  441.     case MOD12:
  442.     case MOD12u:
  443.     case DIV12:
  444.     case DIV12u: gen(SWAP12, 0); break;
  445.     case PUSH1:  csp -= BPW;     break;
  446.     case POP2:   csp += BPW;     break;
  447.     case ADDSP:
  448.     case RETURN: newcsp = value; value -= csp; csp = newcsp;
  449.     }
  450.   if(snext == 0) {
  451.     outcode(pcode, value);
  452.     return;
  453.     }
  454.   if(snext >= slast) {
  455.     error("staging buffer overflow");
  456.     return;
  457.     }
  458.   snext[0] = pcode;
  459.   snext[1] = value;
  460.   snext += 2;
  461.   }
  462.  
  463. /*
  464. ** dump the contents of the queue.
  465. ** If start = 0, throw away contents.
  466. ** If before != 0, don't dump queue yet.
  467. */
  468. clearstage(before, start) int *before, *start; {
  469.   if(before) {
  470.     snext = before;
  471.     return;
  472.     }
  473.   if(start) dumpstage();
  474.   snext = 0;
  475.   }
  476.  
  477. /*
  478. ** dump the staging buffer
  479. */
  480. dumpstage() {
  481.   int i;
  482.   stail = snext;
  483.   snext = stage;
  484.   while(snext < stail) {
  485.     if(optimize) {
  486.       restart:
  487.       i = -1; 
  488.       while(++i <= HIGH_SEQ) if(peep(seq[i])) {
  489. #ifdef DISOPT
  490.         if(isatty(output))
  491.           fprintf(stderr, "                   optimized %2u\n", i);
  492. #endif
  493.         goto restart;
  494.         }
  495.       }
  496.     outcode(snext[0], snext[1]);
  497.     snext += 2;
  498.     }
  499.   }
  500.  
  501. /*
  502. ** change to a new segment
  503. ** may be called with NULL, CODESEG, or DATASEG
  504. */
  505. toseg(newseg) int newseg; {
  506.   if(oldseg == newseg)  return;
  507.   if(oldseg == CODESEG) outline("ENDSEG(2)");
  508.   else if(oldseg == DATASEG) outline("ENDSEG(1)");
  509.   if(newseg == CODESEG)
  510.     outline("TOSEG(2)");
  511.   else if (newseg == DATASEG)
  512.     outline("TOSEG(1)");
  513.   oldseg = newseg;
  514.   }
  515.  
  516. /*
  517. ** declare entry point
  518. */
  519. public(ident) int ident;{
  520.   if(ident == FUNCTION){
  521.        toseg(CODESEG);
  522.       outstr("DECLPUBLIC(");
  523.       outname(ssname);
  524.       outstr(", 2)");
  525.   }
  526.   else {
  527.     toseg(DATASEG);
  528.       outstr("DECLPUBLIC(");
  529.       outname(ssname);
  530.       outstr(", 1)");
  531.   }
  532.   newline();
  533.   }
  534.  
  535. /*
  536. ** declare external reference
  537. */
  538. external(name, size, ident) char *name; int size, ident; {
  539.   if(ident == FUNCTION)
  540.        toseg(CODESEG);
  541.   else toseg(DATASEG);
  542.   outstr("EXTERNAL(");
  543.   outname(name);
  544.   outsize(size, ident);
  545.   newline();
  546.   }
  547.  
  548. /*
  549. ** output the size of the object pointed to.
  550. */
  551. outsize(size, ident) int size, ident; {
  552.   if(size == 1
  553.   && ident != POINTER
  554.   && ident != FUNCTION)      outstr(",BYTE)");
  555.   else if(ident != FUNCTION) outstr(",WORD)");
  556.   else                       outstr(",NEAR)");
  557.   }
  558.  
  559. /*
  560. ** point to following object(s)
  561. */
  562. point() {
  563.   outline(" DW $+2");
  564.   }
  565.  
  566. /*
  567. ** dump the literal pool
  568. */
  569. dumplits(size) int size; {
  570.   int j, k, count;
  571.   k = count = 0;
  572.   if (k < litptr) {
  573.     newline();
  574.     outline("BEGINDUMP");
  575.     }
  576.   while (k < litptr) {
  577.     poll(1);                     /* allow program interruption */
  578.     if(size == 1)
  579.          gen(BYTE_, NULL);
  580.     else gen(WORD_, NULL);
  581.     j = 10;
  582.     while(j--) {
  583.       count++;
  584.       outdec(getint(litq + k, size));
  585.       k += size;
  586.       if(j == 0 || k >= litptr) {
  587.         newline();
  588.         break;
  589.         }
  590.       fputc(',', output);
  591.       }
  592.     }
  593.   if (count) {
  594.     sprintf(tmpbuf, "SHADOW(%d)", (size == 1)? count: count * 2);
  595.     outline(tmpbuf);
  596.     }
  597.   }
  598.  
  599. /*
  600. ** dump zeroes for default initial values
  601. */
  602. dumpzero(size, count) int size, count; {
  603.   if(count > 0) {
  604.     outline("BEGINDUMP");
  605.     if(size == 1)
  606.          gen(BYTEr0, count);
  607.     else gen(WORDr0, count);
  608.     sprintf(tmpbuf, "SHADOW(%d)", (size == 1)? count: count * 2);
  609.     outline(tmpbuf);
  610.     }
  611.   }
  612.  
  613. /******************** optimizer functions ***********************/
  614.  
  615. /*
  616. ** Try to optimize sequence at snext in the staging buffer.
  617. */
  618. peep(seq) int *seq; {
  619.   int *next, *count, *pop, n, skip, tmp, reply;
  620.   char c;
  621.   next = snext;
  622.   count = seq++;
  623.   while(*seq) {
  624.     switch(*seq) {
  625.       case any:   if(next < stail)       break;      return (NO);
  626.       case pfree: if(isfree(PRI, next))  break;      return (NO);
  627.       case sfree: if(isfree(SEC, next))  break;      return (NO);
  628.       case comm:  if(*next & COMMUTES)   break;      return (NO);
  629.       case _pop:  if(pop = getpop(next)) break;      return (NO);
  630.       default:    if(next >= stail || *next != *seq) return (NO);
  631.       }
  632.     next += 2; ++seq;
  633.     }
  634.  
  635.   /****** have a match, now optimize it ******/
  636.  
  637.   *count += 1;
  638.   reply = skip = NO;
  639.   while(*(++seq) || skip) {
  640.     if(skip) {
  641.       if(*seq == 0) skip = NO;
  642.       continue;
  643.       }
  644.     if(*seq >= PCODES) {
  645.       c = *seq & 0xFF;            /* get low byte of command */
  646.       n = c;                      /* and sign extend into n */
  647.       switch(*seq & 0xFF00) {
  648.         case ife:   if(snext[1] != n) skip = YES;  break;
  649.         case ifl:   if(snext[1] >= n) skip = YES;  break;
  650.         case go:    snext += (n<<1);               break;
  651.         case gc:    snext[0] =  snext[(n<<1)];     goto done;
  652.         case gv:    snext[1] =  snext[(n<<1)+1];   goto done;
  653.         case sum:   snext[1] += snext[(n<<1)+1];   goto done;
  654.         case neg:   snext[1] = -snext[1];          goto done;
  655.         case topop: pop[0] = n; pop[1] = snext[1]; goto done;
  656.         case swv:   tmp = snext[1];
  657.                     snext[1] = snext[(n<<1)+1];
  658.                     snext[(n<<1)+1] = tmp;
  659.         done:       reply = YES;
  660.                     break;
  661.         }
  662.       }
  663.     else snext[0] = *seq;         /* set p-code */
  664.     }
  665.   return (reply);
  666.   }
  667.  
  668. /*
  669. ** Is the primary or secondary register free?
  670. ** Is it zapped or unused by the p-code at pp
  671. ** or a successor?  If the primary register is
  672. ** unused by it still may not be free if the
  673. ** context uses the value of the expression.
  674. */
  675. isfree(reg, pp) int reg, *pp; {
  676.   char *cp;
  677.   while(pp < stail) {
  678.     cp = code[*pp];
  679.     if(*cp & USES & reg) return (NO);
  680.     if(*cp & ZAPS & reg) return (YES);
  681.     pp += 2;
  682.     }
  683.   if(usexpr) return (reg & 001);   /* PRI => NO, SEC => YES at end */
  684.   else       return (YES);
  685.   }
  686.  
  687. /*
  688. ** Get place where the currently pushed value is popped?
  689. ** NOTE: Function arguments are not popped, they are
  690. ** wasted with an ADDSP.
  691. */
  692. getpop(next) int *next; {
  693.   char *cp;
  694.   int level;  level = 0;
  695.   while(YES) {
  696.     if(next >= stail)                     /* compiler error */
  697.       return 0;
  698.     if(*next == POP2)
  699.       if(level) --level;
  700.       else return next;                   /* have a matching POP2 */
  701.     else if(*next == ADDSP) {             /* after func call */
  702.       if((level -= (next[1]>>LBPW)) < 0)
  703.         return 0;
  704.       }
  705.     else {
  706.       cp = code[*next];                   /* code string ptr */
  707.       if(*cp & PUSHES) ++level;           /* must be a push */
  708.       } 
  709.     next += 2;
  710.     }
  711.   }
  712.  
  713. /******************* output functions *********************/
  714.  
  715. colon() {
  716.   fputc(':', output);
  717.   }
  718.  
  719. newline() {
  720.   fputc(NEWLINE, output);
  721.   }
  722.  
  723. /*
  724. ** output assembly code.
  725. */
  726. outcode(pcode, value) int pcode, value; {
  727.   int part, skip, count;
  728.   char *cp, *back;
  729.   part = back = 0;
  730.   skip = NO;
  731.   cp = code[pcode] + 1;          /* skip 1st byte of code string */
  732.   while(*cp) {
  733.     if(*cp == '<') {
  734.       ++cp;                      /* skip to action code */
  735.       if(skip == NO) switch(*cp) {
  736.         case 'm': outname(value+NAME); break; /* mem ref by label */
  737.         case 'n': outdec(value);       break; /* numeric constant */
  738.         case 'l': outdec(litlab);      break; /* current literal label */
  739.         }
  740.       cp += 2;                   /* skip past > */
  741.       }
  742.     else if(*cp == '?') {        /* ?..if value...?...if not value...? */
  743.       switch(++part) {
  744.         case 1: if(value == 0) skip = YES; break;
  745.         case 2: skip = !skip;              break;
  746.         case 3: part = 0; skip = NO;       break;
  747.         }
  748.       ++cp;                      /* skip past ? */
  749.       }
  750.     else if(*cp == '#') {        /* repeat #...# value times */
  751.       ++cp;
  752.       if(back == 0) {
  753.         if((count = value) < 1) {
  754.           while(*cp && *cp++ != '#') ;
  755.           continue;
  756.           }
  757.         back = cp;
  758.         continue;
  759.         }
  760.       if(--count > 0) cp = back;
  761.       else back = 0;
  762.       }
  763.     else if(skip == NO) fputc(*cp++, output);
  764.     else ++cp;
  765.     }
  766.   }
  767.  
  768. outdec(number)  int number; {
  769.   int k, zs;
  770.   char c, *q, *r;
  771.   zs = 0;
  772.   k = 10000;
  773.   if(number < 0) {
  774.     number = -number;
  775.     fputc('-', output);
  776.     }
  777.   while (k >= 1) {
  778.     q = 0;
  779.     r = number;
  780.     while(r >= k) {++q; r = r - k;}
  781.     c = q + '0';
  782.     if(c != '0' || k == 1 || zs) {
  783.       zs = 1;
  784.       fputc(c, output);
  785.       }
  786.     number = r;
  787.     k /= 10;
  788.     }
  789.   }
  790.  
  791. outline(ptr)  char ptr[];  {
  792.   outstr(ptr);
  793.   newline();
  794.   }
  795.  
  796. outname(ptr) char ptr[]; {
  797.   outstr("_");
  798.   while(*ptr >= ' ') fputc(*ptr++, output);
  799.   }
  800.  
  801. outstr(ptr) char ptr[]; {
  802.   poll(1);           /* allow program interruption */
  803.   while(*ptr >= ' ') fputc(*ptr++, output);
  804.   }
  805.  
  806.